package com.chenfan.mcn.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.chenfan.common.vo.UserVO;
import com.chenfan.mcn.constant.LogTemplateCst;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.MsgCenterTemplateCst;
import com.chenfan.mcn.dao.CommentLogMapper;
import com.chenfan.mcn.enums.*;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.common.extension.spring.TransactionUtils;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.service.CommentLogService;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.notify.MessageClient;
import com.chenfan.notify.vo.MessageDetailVo;
import com.chenfan.notify.vo.MessagePlanVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lizhejin
 * @since 2021-04-16
 */
@Service
public class CommentLogServiceImpl implements CommentLogService {

    @Autowired
    private CommentLogMapper commentLogMapper;

    @Autowired
    private MessageClient messageClient;

    @Override
    public boolean addComment(CommentAddDTO commentAddDTO) {
        UserVO user = UserVoContextHolder.getUserVo();
        CommentLog commentLog = new CommentLog();
        BeanUtils.copyProperties(commentAddDTO, commentLog);
        commentLog.setCreateBy(user.getUserId());
        commentLog.setCreateName(user.getRealName());
        commentLog.setCreateDate(new Date());
        boolean result = commentLogMapper.insert(commentLog) > 0;
        if (result) {
            //发送应用通知
            this.sendNotify(commentLog);
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(commentLog.getBusinessId())
                    .businessType(this.getLogBusinessType(commentLog.getBusinessType()))
                    .insert(LogTemplateCst.COMMENT_ADD, UserVoContextHolder.getUserName(), commentLog.getBusinessCode())
                    .build());
        }
        return result;
    }

    @Override
    public List<CommentLog> getCommentList(Long businessId, Integer businessType) {
        return commentLogMapper.selectList(Wrappers.lambdaQuery(CommentLog.class)
                .eq(CommentLog::getBusinessId, businessId)
                .eq(CommentLog::getBusinessType, businessType)
                .eq(CommentLog::getIsDelete, Boolean.FALSE)
                .orderByDesc(CommentLog::getCreateDate));
    }

    @Override
    public boolean updateComment(CommentUpdateDTO commentUpdateDTO) {
        CommentLog beforeCommentLog = commentLogMapper.selectOne(Wrappers.lambdaQuery(CommentLog.class)
                .eq(CommentLog::getId, commentUpdateDTO.getId())
                .eq(CommentLog::getIsDelete, Boolean.FALSE));
        Assert.notNull(beforeCommentLog, "评论不存在或已删除");
        CommentLog commentLog = new CommentLog();
        BeanUtils.copyProperties(commentUpdateDTO, commentLog);
        boolean result = commentLogMapper.updateById(commentLog) > 0;
        if (result) {
            commentLog.setBusinessId(beforeCommentLog.getBusinessId());
            commentLog.setBusinessCode(beforeCommentLog.getBusinessCode());
            commentLog.setBusinessType(beforeCommentLog.getBusinessType());
            //发送应用通知
            this.sendNotify(commentLog);
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(commentLog.getBusinessId())
                    .businessType(this.getLogBusinessType(commentLog.getBusinessType()))
                    .compare(beforeCommentLog, commentLog)
                    .build());
        }
        return result;
    }

    @Override
    public CommentLog commentDetail(Long id) {
        UserVO user = UserVoContextHolder.getUserVo();
        CommentLog commentLog = commentLogMapper.selectById(id);
        if (!commentLog.getCreateBy().equals(user.getUserId())) {
            throw new BusinessException(McnErrorCode.ONLY_CREATOR_CAN_UPDATE);
        }
        return commentLogMapper.selectById(id);
    }

    @Override
    public boolean deleteComment(Long id) {
        UserVO user = UserVoContextHolder.getUserVo();
        CommentLog commentLog = commentLogMapper.selectById(id);
        if (!commentLog.getCreateBy().equals(user.getUserId())) {
            throw new BusinessException(McnErrorCode.ONLY_CREATOR_CAN_DELETE);
        }
        commentLog.setIsDelete(NumberCst.ONE);
        boolean result = commentLogMapper.updateById(commentLog) > 0;
        if (result) {
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(commentLog.getBusinessId())
                    .businessType(this.getLogBusinessType(commentLog.getBusinessType()))
                    .delete(LogTemplateCst.COMMENT_DELETE, UserVoContextHolder.getUserName(), commentLog.getBusinessCode())
                    .build());
        }
        return result;
    }



    /**
     * 获取日志业务类型
     * @param businessType
     * @return
     */
    private LogBusinessTypeEnum getLogBusinessType(Integer businessType) {
        if (CommentBusinessTypeEnum.INCOME_CONTRACT.getType().equals(businessType)) {
            return LogBusinessTypeEnum.INCOME_CONTRACT_COMMENT;
        } else if (CommentBusinessTypeEnum.YEAR_FRAME_CONTRACT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.YEAR_FRAME_CONTRACT_COMMENT;
        } else if (CommentBusinessTypeEnum.EXECUTION_ORDER.getType().equals(businessType)) {
             return LogBusinessTypeEnum.EXECUTION_ORDER_COMMENT;
        } else if (CommentBusinessTypeEnum.CLEAR_ORDER.getType().equals(businessType)) {
             return LogBusinessTypeEnum.CLEAR_ORDER_COMMENT;
        } else if (CommentBusinessTypeEnum.TAX_INVOICE.getType().equals(businessType)) {
             return LogBusinessTypeEnum.TAX_INVOICE_COMMENT;
        } else if (CommentBusinessTypeEnum.PURCHASE_CONTRACT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.PURCHASE_CONTRACT_COMMENT;
        } else if (CommentBusinessTypeEnum.DISCOUNT_APPROVAL_ORDER.getType().equals(businessType)) {
             return LogBusinessTypeEnum.DISCOUNT_APPROVAL_COMMENT;
        } else if (CommentBusinessTypeEnum.ANNUAL_REBATE_APPROVAL_ORDER.getType().equals(businessType)) {
             return LogBusinessTypeEnum.ANNUAL_REBATE_APPROVAL_COMMENT;
        } else if (CommentBusinessTypeEnum.STAR_REBATE_CONTRACT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.STAR_REBATE_CONTRACT;
        } else if (CommentBusinessTypeEnum.STAR_MONTHLY_SETTLEMENT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.STAR_MONTHLY_SETTLEMENT;
        } else if (CommentBusinessTypeEnum.SAMPLE_DEVELOPMENT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.SAMPLE_DEVELOPMENT;
        } else if(CommentBusinessTypeEnum.INTENTION_ORDER.getType().equals(businessType)){
             return LogBusinessTypeEnum.INTENTION_ORDER;
        } else if (CommentBusinessTypeEnum.VENDOR_CENTER.getType().equals(businessType)) {
             return LogBusinessTypeEnum.VENDOR_CENTER;
        } else if (CommentBusinessTypeEnum.LIVE_STAR_SETTLEMENT.getType().equals(businessType)) {
             return LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT;
        } else if (CommentBusinessTypeEnum.SAMPLE_PRICING.getType().equals(businessType)) {
            return LogBusinessTypeEnum.SAMPLE_PRICING;
        }
        return null;
    }

    /**
     * 发送通知消息
     *
     * @param commentLog
     */
    private void sendNotify(CommentLog commentLog) {
        if (StringUtils.isBlank(commentLog.getAtJson())) {
            return;
        }
        List<CommentAtPersonDTO> atList = JSONObject.parseObject(commentLog.getAtJson(), new TypeReference<List<CommentAtPersonDTO>>() {});
        if (CollectionUtils.isEmpty(atList)) {
            return;
        }
        TransactionUtils.afterCommit(() -> {
            CommentBusinessTypeEnum commentEnum = CommentBusinessTypeEnum.toEnum(commentLog.getBusinessType());
            MessagePlanVo planVo = new MessagePlanVo();
            planVo.setTenantId(ObjectUtils.defaultIfNull(commentLog.getTenantId(), 1L));
            planVo.setMessageKey(CommonUtil.getMessageKey(commentLog.getBusinessCode()));
            planVo.setJumpUrlType(commentEnum.getJumpUrlType());
            if (CommentBusinessTypeEnum.SAMPLE_DEVELOPMENT.getType().equals(commentLog.getBusinessType()) || CommentBusinessTypeEnum.SAMPLE_PRICING.getType().equals(commentLog.getBusinessType())) {
                planVo.setTemplate(MsgCenterTemplateCst.SCM_COMMENT_AT);
            } else {
                planVo.setTemplate(MsgCenterTemplateCst.COMMENT_AT);
            }
            List<MessageDetailVo> details = new ArrayList<>(atList.size());
            atList.forEach(data -> {
                MessageDetailVo messageDetailVo = new MessageDetailVo();
                messageDetailVo.setUserId(data.getUserId());
                Map<String, String> externParams = new HashMap<>(3);
                externParams.put("url", commentEnum.getUrl());
                externParams.put("businessId", commentLog.getBusinessId().toString());
                externParams.put("userName", UserVoContextHolder.getUserName());
                externParams.put("name", commentEnum.getDesc());
                externParams.put("code", commentLog.getBusinessCode());
                messageDetailVo.setExternParams(externParams);
                details.add(messageDetailVo);
            });
            planVo.setDetails(details);
            messageClient.sendMessage(planVo);
        });
    }
}
